package xine.demo.ssm.view;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.view.AbstractView;

import xine.demo.ssm.constant.ViewContant;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Controller(ViewContant.VIEW_EXCEL)
public class SingleExcelView extends AbstractView {

    public static final String EXCEL_TYPE_HSSF = "hssf";

    /**
     * 注解对象
     */
    public final static String CLASS = "entity";
    /**
     * 表格参数
     */
    public final static String PARAMS = "params";
    /**
     * 下载文件名称
     */
    public final static String FILE_NAME = "fileName";

    /**
     * 单Sheet导出
     */
    public final static String JEECG_EXCEL_VIEW = "jeecgExcelView";
    /**
     * 数据列表
     */
    public final static String DATA_LIST = "data";
    /**
     * 多Sheet 对象
     */
    public final static String MAP_LIST = "mapList";

    protected static final String HSSF = ".xls";
    protected static final String XSSF = ".xlsx";


    public SingleExcelView() {
    }

    @Override
    protected boolean generatesDownloadContent() {
        return true;
    }


    //输出结果，作为响应
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

        List<Map<String, Object>> list = (List<Map<String, Object>>) model.get(MAP_LIST);
        if (list.size() == 0) {
            throw new RuntimeException("MAP_LIST IS NULL");
        }

        //创建WorkBook （直接创建，另一种是利用注解创建）
        Workbook workbook = createWorkbook(list, null);

        // Delegate to application-provided document code.
        buildExcelDocument(model, workbook, request, response);

        String codedFileName = "临时文件";

        if (model.containsKey(FILE_NAME)) {
            codedFileName = (String) model.get(FILE_NAME);
        }
        if (workbook instanceof HSSFWorkbook) {
            codedFileName += HSSF;
        } else {
            codedFileName += XSSF;
        }
        if (isIE(request)) {
            codedFileName = java.net.URLEncoder.encode(codedFileName, "UTF8");
        } else {
            codedFileName = new String(codedFileName.getBytes("UTF-8"), "ISO-8859-1");
        }

        //设置response
        if (workbook instanceof HSSFWorkbook) {
            setContentType("application/vnd.ms-excel"); //用于xls
        } else {
            setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //用于xlsx
        }

        // Flush byte array to servlet output stream.
        renderWorkbook(workbook, codedFileName, response);
    }

    /**
     * 创建workbook
     *
     * @param list
     * @param type
     * @return
     */
    public static Workbook createWorkbook(List<Map<String, Object>> list, String type) {
        Workbook workbook;
        if (EXCEL_TYPE_HSSF.equals(type)) {
            workbook = new HSSFWorkbook();
        } else if (list.size() < 1000) {
            workbook = new XSSFWorkbook();
        } else {
            workbook = new SXSSFWorkbook();
        }

        return workbook;
    }

    protected boolean isIE(HttpServletRequest request) {
        return (request.getHeader("USER-AGENT").toLowerCase().indexOf("msie") > 0 || request
                .getHeader("USER-AGENT").toLowerCase().indexOf("rv:11.0") > 0) ? true : false;
    }

    /**
     * The actual render step: taking the POI {@link Workbook} and rendering
     * it to the given response.
     *
     * @param workbook      the POI Workbook to render
     * @param codedFileName 文件名
     * @param response      current HTTP response
     * @throws IOException when thrown by I/O methods that we're delegating to
     */
    protected void renderWorkbook(Workbook workbook, String codedFileName, HttpServletResponse response) throws IOException {

        response.setHeader("content-disposition", "attachment;filename=" + codedFileName);
        ServletOutputStream out = response.getOutputStream();
        workbook.write(out);
        out.flush();

        if (workbook instanceof Closeable) {
            ((Closeable) workbook).close();
        }

    }

    protected void buildExcelDocument(
            Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        //创建sheet
        Sheet sheet1 = workbook.createSheet("sheet1");

        CellStyle cellStyle = sheet1.getColumnStyle(0);//获取列风格

        for (int rowIndex = 0; rowIndex < 10; rowIndex++) {
            Row row = sheet1.createRow(rowIndex);

            for (int column = 0; column < 6; column++) {
                Cell cell = row.createCell(column);
                cell.setCellStyle(cellStyle);//设置单元风格
                cell.setCellValue("test_" + rowIndex + "_" + column);
            }
        }

    }
}
